package com.zbkj.front.netty.server;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.zbkj.common.constants.Constants;
import com.zbkj.common.constants.RedisConstants;
import com.zbkj.common.netty.AcceptDataContent;
import com.zbkj.common.utils.RedisUtil;
import com.zbkj.service.service.SendMessageService;
import com.zbkj.service.websocket.ChannelQueueDTO;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.handler.codec.http.*;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketServerHandshaker;
import io.netty.handler.codec.http.websocketx.WebSocketServerHandshakerFactory;
import io.netty.util.concurrent.GlobalEventExecutor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;

import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * YtydnHandler
 * </p>
 *
 * @author ywy
 * @since 2021-08-05
 */
@Slf4j
@ChannelHandler.Sharable
public class YgxHandler extends ChannelInboundHandlerAdapter {

    private static RedisUtil redisUtil;
    private static SendMessageService sendMessageService;


    static {
        redisUtil = SpringUtils.getBean(RedisUtil.class);
        sendMessageService = SpringUtils.getBean(SendMessageService.class);
    }


    /**
     * 定义一个channel组，管理所有的channel
     * GlobalEventExecutor.INSTANCE 是全局的事件执行器，是一个单例
     */
    public static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

    public static Channel findChannelById(String id) {
        for (Channel channel : channelGroup) {
            if (channel.id().asLongText().equals(id)) {
                return channel;
            }
        }
        return null;
    }

    /**
     * 一旦连接,第一个被执行,将添加到channelGroup通道组统一管理
     *
     * @param ctx ctx
     * @throws Exception
     */
    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        //添加到channel组统一管理
        channelGroup.add(ctx.channel());
        log.info("新连接进来了,连接的channelId是:{}, 当前连接数：{}", ctx.channel().id().asLongText(),channelGroup.size());
    }


    /**
     * 读取数据
     *
     * @param ctx ctx
     * @param msg xx
     * @throws Exception
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        if (msg instanceof TextWebSocketFrame) {
            //正常的TEXT消息类型
            TextWebSocketFrame frame = (TextWebSocketFrame) msg;
            String text = frame.text();

            if ("PING".equals(text)) {
                // 心跳检测
                ctx.channel().writeAndFlush(new TextWebSocketFrame("PONG"));
                return;
            }

            log.info("接收到的参数是：{}   msg:{}", text, msg);
            Boolean flag = checkJson(text);
            if (!flag) {
                ctx.channel().writeAndFlush(new TextWebSocketFrame("不是json格式的数据"));
                return;
            }
            AcceptDataContent acceptDataContent = JSONUtil.toBean(text, AcceptDataContent.class);
            if (acceptDataContent == null || acceptDataContent.getMessageType() == null) {
                return;
            }

            //添加绑定关系
            if (0 == acceptDataContent.getMessageType()) {
                Boolean isSuccess = sendMessageService.login(acceptDataContent, ctx.channel());
                if (!isSuccess)
                    this.channelInactive(ctx);
            }

            //app发送文字
//            else if (Constants.CHANNEL_SECRET_SEND_MESSAGE.equals(acceptDataContent.getSecret())) {
//                sendMessageService.forwardMessage(acceptDataContent);
//            }
            //APP端待机心跳
//            else if (3 == acceptDataContent.getType()) {
//                TbUser tbUser = iTbUserService.getUserByUserId(userId);
//                Integer standbyDuration = tbUser.getStandbyDuration() * 60;
//                Long timeoutMillis = (long) (standbyDuration * 1000);
//                redisUtil.sset(ResultStatus.APP_STANDBY_DURATION.concat(tbUser.getUserId()), tbUser.getUserId() + ":" + standbyDuration, standbyDuration - 30);
//                rabbitSender.sendTtlNoTran(QueueEnum.QUEUE_APP_HEARTBEAT_PLUGIN_STANDBY, tbUser.getUserId(), timeoutMillis, null);
//            }
//
//            //CAP端待机心跳
//            else if (5 == acceptDataContent.getType()) {
////                TbUser tbUser = iTbComputerService.getTbUserByUserPcId(userId);
//////                if (tbUser != null) {
//////                    Integer standbyDuration = tbUser.getStandbyDuration() * 60;
//////                    Long timeoutMillis = Long.valueOf(standbyDuration * 1000);
//////                    redisUtil.sset(ResultStatus.CAP_STANDBY_DURATION.concat(tbUser.getUserId()), tbUser.getUserId() + ":" + standbyDuration, standbyDuration - 30);
//////                    rabbitSender.sendTtlNoTran(QueueEnum.QUEUE_APP_HEARTBEAT_STANDBY_NEW, tbUser.getUserId(), timeoutMillis, null);
//////                }
//            }
            //cap采集端的心跳
//            else if (12 == acceptDataContent.getType()) {
//                ComputerInfo computerInfo = acceptDataContent.getComputerInfo();
//                //更新gpu
//                iTbComputerService.updateComputer(userId, computerInfo);
//                //检测心跳状态
//                redisUtil.hset(ResultStatus.CAP_STANDBY_DURATION, userId, Instant.now().toEpochMilli(), 0);
//                rabbitSender.sendTtlNoTran(QueueEnum.QUEUE_CAP_HEARTBEAT_STANDBY, userId, ResultStatus.CAP_TIMEOUT_MILLIS, null);
//                //ping pong message
//                iTbComputerService.replyPongMessage(ctx.channel(), acceptDataContent, 12);
//            }
//            //cap采集端的登录
//            else if (13 == acceptDataContent.getType()) {
//                //更新上线状态
//                iTbComputerService.updateComputerStatus(userId);
//            }
//            //ios端待机心跳
//            else if (23 == acceptDataContent.getType()) {
//                TbUser tbUser = iTbUserService.getUserByUserId(userId);
//                Integer standbyDuration = tbUser.getStandbyDuration() * 60;
//                Long timeoutMillis = Long.valueOf(standbyDuration * 1000);
//                redisUtil.sset(ResultStatus.APP_STANDBY_DURATION.concat(tbUser.getUserId()), tbUser.getUserId() + ":" + standbyDuration, standbyDuration - 30);
//                rabbitSender.sendTtlNoTran(QueueEnum.QUEUE_APP_HEARTBEAT_PLUGIN_STANDBY, tbUser.getUserId(), timeoutMillis, null);
//            }

            log.info("客户端发来了消息channelId是:{},消息的内容是:{},当前连接数是：{}", ctx.channel().id().asLongText(), acceptDataContent, channelGroup.size());
        }
    }


    /**
     * 校验是否为json格式
     *
     * @param text
     * @return
     */
    private Boolean checkJson(String text) {
        boolean flag = true;
        try {
            JSONUtil.toBean(text, AcceptDataContent.class);
        } catch (Exception e) {
            flag = false;
        }
        return flag;
    }


    /**
     * 正常移除连接
     *
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        String asLongText = ctx.channel().id().asLongText();
        log.info("退出连接 {}", asLongText);
        //移除连接
        channelGroup.remove(ctx.channel());
        sendMessageService.logout(ctx.channel());
        log.info("当前连接数是：{}", channelGroup.size());

    }
/*    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        String asLongText = ctx.channel().id().asLongText();
        //得到用户id
        String userId = UserIdChannelMap.findUserIdByChannelId(asLongText);
        //是采集端的移除
        if (StrUtil.isNotBlank(userId) && userId.startsWith(ResultStatus.CAP)) {
            //异常退出扣费
            TbComputer tbComputer = iTbComputerService.getByUserPcId(userId);
            if (tbComputer != null) {
                TbUserComputerTime tbUserComputerTime = iTbUserComputerTimeService.getUserIdByComputerId(tbComputer.getId());
                if (tbUserComputerTime != null) {
                    //异常退出扣费
                    iTbComputerService.signOutCloudComputer(tbUserComputerTime.getUserId(), 4);
                    //云电脑异常退出,通知移动端用户退出云电脑
                    iTbComputerService.exceptionLogoutByUserId(tbUserComputerTime.getUserId());
                }
            } else {
                //更新云电脑状态
                iTbComputerService.updateStatus(userId, 0);
            }
            //移除连接
            channelGroup.remove(ctx.channel());
            if (StrUtil.isNotBlank(userId)) {
                log.info("正常退出的channelId是:{},正常退出的userId是:{},当前连接数是：{}", asLongText, userId, channelGroup.size());
            }
            //解除绑定关系
            //UserIdChannelMap.remove(userId);
        }
        //安卓移动端的移除new
        else if (StrUtil.isNotBlank(userId) && !userId.startsWith(ResultStatus.CAP)) {
            log.info("安卓移动端的正常移除,用户id是：{}", userId);
            //用户待机
            iTbUserService.standby(userId);
            //没有就是排队用户
            TbUser tbUser = iTbUserService.getUserByUserIdNetty(userId);
            //取消排队
            iTbUserService.cancelLineUp(tbUser);
        }
        //安卓移动端的移除old
//        else if (StrUtil.isNotBlank(userId) && !userId.startsWith(ResultStatus.CAP)) {
//            //查询是否有正在使用的云电脑
//            TbUserComputerTime tbUserComputerTime = iTbUserComputerTimeService.getTbUserComputerTime(userId);
//            if (tbUserComputerTime != null) {
//                //正常退出扣费
//                iTbComputerService.signOutCloudComputer(userId, 2);
//                //更新用户排队信息状态
//                iTbUserLineUpQueueService.updateIsCancelByUserId(userId, 2);
//            } else {
//                //没有就是排队用户
//                TbUser tbUser = iTbUserService.getUserByUserIdNetty(userId);
//                //取消排队
//                if (tbUser != null) {
//                    iTbUserService.cancelLineUp(tbUser);
//                }
//            }
//            log.info("正常退出的channelId是:{},正常退出的userId是:{},当前连接数是：{}", asLongText, userId, channelGroup.size());
//        }


    }*/


    /**
     * 异常退出
     *
     * @param ctx
     * @param
     * @throws Exception
     */
//    @Override
//    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
//        String asLongText = ctx.channel().id().asLongText();
//        //得到用户id
//        String userId = UserIdChannelMap.findUserIdByChannelId(asLongText);
//        //是采集端的异常退出移除
//        if (StrUtil.isNotBlank(userId) && userId.startsWith(ResultStatus.CAP)) {
//            //异常退出扣费
//            TbComputer tbComputer = iTbComputerService.getByUserPcId(userId);
//            if (tbComputer != null) {
//                TbUserComputerTime tbUserComputerTime = iTbUserComputerTimeService.getUserIdByComputerId(tbComputer.getId());
//                if (tbUserComputerTime != null) {
//                    //异常退出扣费
//                    iTbComputerService.signOutCloudComputer(tbUserComputerTime.getUserId(), 5);
//                    //云电脑异常退出,通知移动端用户退出云电脑
//                    iTbComputerService.exceptionLogoutByUserId(tbUserComputerTime.getUserId());
//                }
//            }
//            //更新云电脑状态
//            iTbComputerService.updateStatus(userId, 0);
//            //移除,不写也行
//            channelGroup.remove(ctx.channel());
//            if (StrUtil.isNotBlank(userId)) {
//                log.info("异常退出的channelId是:{},异常退出的userId是:{},当前连接数是：{}", asLongText, userId, channelGroup.size());
//            }
//            //解除绑定关系
//            UserIdChannelMap.remove(userId);
//        }
//        //安卓移动端异常退出移除new
//        else if (StrUtil.isNotBlank(userId) && !userId.startsWith(ResultStatus.CAP)) {
//            log.info("安卓移动端异常退出移除,用户id是：{}", userId);
//            //没有就是排队用户
//            TbUser tbUser = iTbUserService.getUserByUserId(userId);
//            //取消排队
//            iTbUserService.cancelLineUp(tbUser);
//        }
//
//        //安卓移动端异常退出移除old
////        else if (StrUtil.isNotBlank(userId) && !userId.startsWith(ResultStatus.CAP)) {
////            //查询是否有正在使用的云电脑
////            TbUserComputerTime tbUserComputerTime = iTbUserComputerTimeService.getTbUserComputerTime(userId);
////            if (tbUserComputerTime != null) {
////                //异常退出扣费
////                iTbComputerService.signOutCloudComputer(userId, 3);
////                //更新用户排队信息状态
////                iTbUserLineUpQueueService.updateIsCancelByUserId(userId, 1);
////            } else {
////                //没有就是排队用户
////                TbUser tbUser = iTbUserService.getUserByUserIdNetty(userId);
////                //取消排队
////                iTbUserService.cancelLineUp(tbUser);
////            }
////            //移除,不写也行
////            channelGroup.remove(ctx.channel());
////            log.info("异常退出的channelId是:{},异常退出的userId是:{},当前连接数是：{}", asLongText, userId, channelGroup.size());
////        }
//
//
//    }
//    @Override
//    public void userEventTriggered(final ChannelHandlerContext ctx, Object evt) throws Exception {
//        if (evt instanceof IdleStateEvent) {
//            IdleStateEvent event = (IdleStateEvent) evt;
//            if (event.state() == IdleState.ALL_IDLE) {
//                //得到用户id
//                String userId = UserIdChannelMap.findUserIdByChannelId(ctx.channel().id().asLongText());
//                if (StrUtil.isNotBlank(userId)) {
//                    log.info("读写空闲,读写空闲的用户id是:{}", userId);
//                }
//                //是采集端的读写空闲移除
//                if (StrUtil.isNotBlank(userId) && userId.startsWith(ResultStatus.CAP)) {
//                    //异常退出扣费
//                    TbComputer tbComputer = iTbComputerService.getByUserPcId(userId);
//                    if (tbComputer != null) {
//                        TbUserComputerTime tbUserComputerTime = iTbUserComputerTimeService.getUserIdByComputerId(tbComputer.getId());
//                        if (tbUserComputerTime != null) {
//                            //异常退出扣费
//                            iTbComputerService.signOutCloudComputer(tbUserComputerTime.getUserId(), 7);
//                            //云电脑异常退出,通知移动端用户退出云电脑
//                            iTbComputerService.exceptionLogoutByUserId(tbUserComputerTime.getUserId());
//                        }
//                    }
//                    //更新云电脑状态
//                    iTbComputerService.updateStatus(userId, 0);
//                }
//                //是安卓移动端的读写空闲移除
//                else if (StrUtil.isNotBlank(userId) && !userId.startsWith(ResultStatus.CAP)) {
//                    //查询是否有正在使用的云电脑
//                    TbUserComputerTime tbUserComputerTime = iTbUserComputerTimeService.getTbUserComputerTime(userId);
//                    if (tbUserComputerTime != null) {
//                        //异常退出扣费
//                        iTbComputerService.signOutCloudComputer(userId, 6);
//                        //更新用户排队信息状态
//                        iTbUserLineUpQueueService.updateIsCancelByUserId(userId, 1);
//                    } else {
//                        //没有就是排队用户
//                        TbUser tbUser = iTbUserService.getUserByUserIdNetty(userId);
//                        if (tbUser != null) {
//                            //取消排队
//                            iTbUserService.cancelLineUp(tbUser);
//                        }
//                    }
//                }
//                //移除,不写也行
//                channelGroup.remove(ctx.channel());
//                if (StrUtil.isBlank(userId)) {
//                    ctx.channel().close();
//                }
//                //解除绑定关系
//                UserIdChannelMap.remove(userId);
//            } else if (event.state() == IdleState.READER_IDLE) {
//                //得到用户id
//                String userId = UserIdChannelMap.findUserIdByChannelId(ctx.channel().id().asLongText());
//                ctx.channel().close();
//                if (StrUtil.isNotBlank(userId)) {
//                    //log.info("读空闲,读空闲的用户id是:{}", userId);
//                }
//
//            } else if (event.state() == IdleState.WRITER_IDLE) {
//                //得到用户id
//                String userId = UserIdChannelMap.findUserIdByChannelId(ctx.channel().id().asLongText());
//                if (StrUtil.isNotBlank(userId)) {
//                    //log.info("写空闲,写空闲的用户id是:{}", userId);
//                }
//            }
//        }
//    }


}
